AWS CLIでスタックのアウトプットパラメータを取得する
こんにちは、コンサル部の鈴木(純)です。
最近AWS CLIを使ってCloudFormationスタックのアウトプットパラメータを取得したことがあったので、メモとして共有します。
どんなときに便利か
私がAWS CLIを使ってCloudFormationスタックのアウトプットパラメータを取得しようと思ったのは、以下のような条件の場合でした。
- 対象のリソースがCloudFormationで対応していない
- 対象のリソースがAWS CLIでは作成できる
- マネージメントコンソールからリソースを作成したくない
- CloudFormationのスタックで作成したリソースを参照したい
多くのリソースに対応しているCloudFormationですが、全てのリソースに対応しているというわけではないので、どうしても対応できない部分はあります。私の場合はAD ConnectorがCloudFormationに対応していなかったので、事前にCloudFormationで作成したVPCやサブネットの情報を取得してAWS CLIで作成する方法を検討しました。
やってみる
それでは早速実際にCloudFormationのスタックを展開してAWS CLIでアウトプットしたパラメータを取得していきます。今回jsonの整形を行う部分では、AWS CLIオプションのquery
でもできるのですが、
使い方がよく分かっていないので
jq
で行っています。
実行環境
- macOS Catalina 10.15.7
- AWS CLI V2
- jq 1.6
スタックの展開
単純にVPCとパブリックサブネット2つ、プライベートサブネットを2つを定義したNetworkStack
を展開しています。
全部のテンプレートを載せると量が多いので、アウトプットしているパラメータだけ載せておきます。
Outputs: Vpc: Value: !Ref Vpc Export: Name: !Sub ${AWS::StackName}-Vpc PublicSubnetAZ1: Value: !Ref PublicSubnetAZ1 Export: Name: !Sub ${AWS::StackName}-PublicSubnetAZ1 PublicSubnetAZ2: Value: !Ref PublicSubnetAZ2 Export: Name: !Sub ${AWS::StackName}-PublicSubnetAZ2 PrivateSubnetAZ1: Value: !Ref PrivateSubnetAZ1 Export: Name: !Sub ${AWS::StackName}-PrivateSubnetAZ1 PrivateSubnetAZ2: Value: !Ref PrivateSubnetAZ2 Export: Name: !Sub ${AWS::StackName}-PrivateSubnetAZ2 #Cidr output VpcCidr: Value: !Ref VpcCidr Export: Name: !Sub ${AWS::StackName}-VpcCidr PublicSubnetAZ1Cidr: Value: !Ref PublicSubnetAZ1Cidr Export: Name: !Sub ${AWS::StackName}-PublicSubnetAZ1Cidr PublicSubnetAZ2Cidr: Value: !Ref PublicSubnetAZ2Cidr Export: Name: !Sub ${AWS::StackName}-PublicSubnetAZ2Cidr PrivateSubnetAZ1Cidr: Value: !Ref PrivateSubnetAZ1Cidr Export: Name: !Sub ${AWS::StackName}-PrivateSubnetAZ1Cidr PrivateSubnetAZ2Cidr: Value: !Ref PrivateSubnetAZ2Cidr Export: Name: !Sub ${AWS::StackName}-PrivateSubnetAZ2Cidr
例えばVPCのIDを取得したい場合、CloudFormationの別スタックから参照するときはImportValue
を使えばいいですが、今回はAWS CLIから取得する必要があります。
CloudFormationスタックからCLIで情報を取得する
CloudFormationのスタック情報を取得するAWS CLIはdescribe-stacks
を使えば取得できます。
今回はスタックの名前はNetworkStack
としているので、オプションでスタック名を指定してあげましょう。実行すると以下のようなjsonのレスポンスが返ってきました。
$ aws cloudformation describe-stacks --stack-name NetworkStack "Stacks": [ { "StackId": "arn:aws:cloudformation:ap-northeast-1:xxxxxxxxxxxx:stack/NetworkStack/cdc61ce0-1d64-11eb-954e-0a683702510a", "StackName": "NetworkStack", "ChangeSetId": "arn:aws:cloudformation:ap-northeast-1:xxxxxxxxxxxx:changeSet/awscli-cloudformation-package-deploy-1604360434/4cd2f8d3-1e6b-4b63-be1c-c8641e8f982f", "Parameters": [ { "ParameterKey": "PublicSubnetAZ2Cidr", "ParameterValue": "10.0.1.0/24" }, { "ParameterKey": "PrivateSubnetAZ2Cidr", "ParameterValue": "10.0.3.0/24" }, { "ParameterKey": "VpcCidr", "ParameterValue": "10.0.0.0/16" }, { "ParameterKey": "SystemName", "ParameterValue": "test" }, { "ParameterKey": "Env", "ParameterValue": "dev" }, { "ParameterKey": "PrivateSubnetAZ1Cidr", "ParameterValue": "10.0.2.0/24" }, { "ParameterKey": "PublicSubnetAZ1Cidr", "ParameterValue": "10.0.0.0/24" } ], "CreationTime": "2020-11-02T23:40:35.489000+00:00", "LastUpdatedTime": "2020-11-02T23:40:40.957000+00:00", "RollbackConfiguration": {}, "StackStatus": "CREATE_COMPLETE", "DisableRollback": false, "NotificationARNs": [], "Capabilities": [ "CAPABILITY_NAMED_IAM" ], "Outputs": [ { "OutputKey": "PublicSubnetAZ1", "OutputValue": "subnet-0d83a103c6102239e", "ExportName": "NetworkStack-PublicSubnetAZ1" }, { "OutputKey": "PublicSubnetAZ2Cidr", "OutputValue": "10.0.1.0/24", "ExportName": "NetworkStack-PublicSubnetAZ2Cidr" }, { "OutputKey": "PublicSubnetAZ2", "OutputValue": "subnet-03da5606647c8e00d", "ExportName": "NetworkStack-PublicSubnetAZ2" }, { "OutputKey": "PrivateSubnetAZ2Cidr", "OutputValue": "10.0.3.0/24", "ExportName": "NetworkStack-PrivateSubnetAZ2Cidr" }, { "OutputKey": "VpcCidr", "OutputValue": "10.0.0.0/16", "ExportName": "NetworkStack-VpcCidr" }, { "OutputKey": "Vpc", "OutputValue": "vpc-06fed38823bb2c6d8", "ExportName": "NetworkStack-Vpc" }, { "OutputKey": "PrivateSubnetAZ1Cidr", "OutputValue": "10.0.2.0/24", "ExportName": "NetworkStack-PrivateSubnetAZ1Cidr" }, { "OutputKey": "PrivateSubnetAZ2", "OutputValue": "subnet-0f75156fd2c2bba26", "ExportName": "NetworkStack-PrivateSubnetAZ2" }, { "OutputKey": "PrivateSubnetAZ1", "OutputValue": "subnet-018273f9dd6a65b2b", "ExportName": "NetworkStack-PrivateSubnetAZ1" }, { "OutputKey": "PublicSubnetAZ1Cidr", "OutputValue": "10.0.0.0/24", "ExportName": "NetworkStack-PublicSubnetAZ1Cidr" } ], "Tags": [], "EnableTerminationProtection": false, "DriftInformation": { "StackDriftStatus": "NOT_CHECKED" } } ] }
出力の詳細についてAWS CLIのドキュメントをご参照下さい。
describe-stacks - AWS CLI 2.0.61 Command Reference
あとはこの取得したjsonから欲しい値を取得していきます。
取得したjsonからアウトプットパラメータを取得する
jsonから値を取得するために、今回は jq を使用します。
インストールしていない方は以下のコマンドを実行してください。
sudo yum -y install jq
まずはjsonの中のOutputs
を取得していきましょう。先ほどのコマンドで取得したjsonからjqを使って整形します。
$ aws cloudformation describe-stacks --stack-name NetworkStack | jq -r '.Stacks[] | .Outputs[]' { "OutputKey": "PublicSubnetAZ1", "OutputValue": "subnet-0d83a103c6102239e", "ExportName": "NetworkStack-PublicSubnetAZ1" } { "OutputKey": "PublicSubnetAZ2Cidr", "OutputValue": "10.0.1.0/24", "ExportName": "NetworkStack-PublicSubnetAZ2Cidr" } { "OutputKey": "PublicSubnetAZ2", "OutputValue": "subnet-03da5606647c8e00d", "ExportName": "NetworkStack-PublicSubnetAZ2" } { "OutputKey": "PrivateSubnetAZ2Cidr", "OutputValue": "10.0.3.0/24", "ExportName": "NetworkStack-PrivateSubnetAZ2Cidr" } { "OutputKey": "VpcCidr", "OutputValue": "10.0.0.0/16", "ExportName": "NetworkStack-VpcCidr" } { "OutputKey": "Vpc", "OutputValue": "vpc-06fed38823bb2c6d8", "ExportName": "NetworkStack-Vpc" } { "OutputKey": "PrivateSubnetAZ1Cidr", "OutputValue": "10.0.2.0/24", "ExportName": "NetworkStack-PrivateSubnetAZ1Cidr" } { "OutputKey": "PrivateSubnetAZ2", "OutputValue": "subnet-0f75156fd2c2bba26", "ExportName": "NetworkStack-PrivateSubnetAZ2" } { "OutputKey": "PrivateSubnetAZ1", "OutputValue": "subnet-018273f9dd6a65b2b", "ExportName": "NetworkStack-PrivateSubnetAZ1" } { "OutputKey": "PublicSubnetAZ1Cidr", "OutputValue": "10.0.0.0/24", "ExportName": "NetworkStack-PublicSubnetAZ1Cidr" }
いい感じにOutputs
の中を取得できましたね。あとはこの中からkeyを指定して欲しい値を取得していきます。
VPCのIDを取得する
先ほどはアウトプットしたパラメータを全て取得していましたが、次にVPCのIDを取得していきます。
先ほどのjsonで言えばVPCは以下のあたりですね。欲しい値はvpc-06fed38823bb2c6d8
です。
{ "OutputKey": "Vpc", "OutputValue": "vpc-06fed38823bb2c6d8", "ExportName": "NetworkStack-Vpc" }
まずはこの情報を取得していきたいので、OutputKey
がVpc
のものを jq の select で取得していきます。
$ aws cloudformation describe-stacks --stack-name NetworkStack | jq -r '.Stacks[] | .Outputs[] | select(.OutputKey == "Vpc")' { "OutputKey": "Vpc", "OutputValue": "vpc-06fed38823bb2c6d8", "ExportName": "NetworkStack-Vpc" }
想定通りに取得することができました。今回はOutputValue
の値が欲しいので、ここからさらに絞りこみます。
$ aws cloudformation describe-stacks --stack-name NetworkStack | jq -r '.Stacks[] | .Outputs[] | select(.OutputKey == "Vpc") | .OutputValue ' vpc-06fed38823bb2c6d8
これでようやく欲しかったVPCのIDを取得することができました。あとはこの値をシェルの中で変数に入れるなりして自由に使うことができます。
他のアウトプットリソースを取得したい場合は、select(.OutputKey == "Vpc")
で指定しているVpc
を他の値に変更してあげましょう。
Public Subnet 1
のSubnet IDが欲しい場合
$ aws cloudformation describe-stacks --stack-name NetworkStack | jq -r '.Stacks[] | .Outputs[] | select(.OutputKey == "PublicSubnetAZ1") | .OutputValue ' subnet-0d83a103c6102239e
Private Subnet 1
のCIDRが欲しい場合
$ aws cloudformation describe-stacks --stack-name NetworkStack | jq -r '.Stacks[] | .Outputs[] | select(.OutputKey == "PrivateSubnetAZ1Cidr") | .OutputValue ' 10.0.2.0/24
これで欲しい値をいい感じに取得することができるようになりました。
まとめ
AWS CLIで事前に作成したスタックのアウトプットパラメータを取得してみました。CloudFormationに対応していないリソース作成のとき、たまに使うことがありそうなので是非覚えておきましょう!